"""
CREATE: 2018/5/12
AUTHOR:　HEHAHUTU
"""
from flask_restful import Resource, reqparse, fields, marshal_with
from app.api import api
from app.models.admin.user import User, UserAvatar
from app.models.admin.config import FConfig
from f_lib.code import Msg
from settings import UPLOAD_PATH
import os
from f_lib.marshal_list import marshal
from f_lib.principal.auth import auth_token
from f_lib.tool.email import send_email_html
from flask import g, make_response
from werkzeug.datastructures import FileStorage
from app.models.admin.code import LCode
from f_lib.tool.email_template import code_template
from f_lib.principal.safety import safety_strategy
from flask import request
from app.models.share.shareList import ShareKey, ShareShip
from concurrent.futures import ThreadPoolExecutor

executor = ThreadPoolExecutor(max_workers=10)



class HelloWorld(Resource):
    def get(self):
        return Msg.success('hello word')


user_parser = reqparse.RequestParser()
user_parser.add_argument('username', type=str, required=True)
user_parser.add_argument('name', type=str, required=True)
user_parser.add_argument('email', type=str, required=True)
user_parser.add_argument('password', type=str, required=True)
user_parser.add_argument('phone', type=str)

user_get_parser = reqparse.RequestParser()
user_get_parser.add_argument('assess_key', help='uid is required', type=int, required=True)

user_fields = {
    'id': fields.Integer,
    'name': fields.String,
    'email': fields.String,
}


class CtlUser(Resource):
    @safety_strategy
    @auth_token()
    def get(self):
        to_base = dict(
            name=None,
            username=None,
            email=None,
            phone=None,
            max_size=None,
            use_size=None,
            # roles=None
        )
        da = marshal(to_base, g.user)
        da['uid'] = g.user.id
        size_progress = (g.user.use_size/g.user.max_size)*100
        return Msg.success('ok', progress=round(size_progress, 2), roles=g.user.roles.value, **da)

    @safety_strategy
    def post(self):
        config = FConfig.query_one()
        if config:
            if config.is_register == 1:
                arg = user_parser.parse_args()
                arg['roles'] = config.default_reg_role
                user = User.create(**arg)
                use_folder = user.use_folder
                os.mkdir(os.path.join(UPLOAD_PATH, use_folder))
                return Msg.success(**marshal(user_fields, user))
            return Msg.failed_dict(2005)
        return Msg.failed('系统错误！')


class UpdateUser(Resource):
    parse = reqparse.RequestParser()
    parse.add_argument('name', type=str)
    parse.add_argument('phone', type=str)

    @auth_token()
    def post(self):
        arg = self.parse.parse_args()
        g.user.update(**arg)
        return Msg.success('修改成功')


class UpdateEmail(Resource):
    parse = reqparse.RequestParser()
    parse.add_argument('email', type=str, required=True)

    @auth_token()
    def get(self):
        arg = self.parse.parse_args()
        g.user.update(**arg)
        return Msg.success()

    @safety_strategy
    @auth_token()
    def post(self):
        arg = self.parse.parse_args()
        # if g.user.email_stat !=1:
        #     return Msg.failed_dict(6001)
        config = FConfig.query_one()
        email_admin = config.email_info
        host = config.host
        url = host + '/user/email?assess_key='+g.assess_key+'&email='+arg.get('email')
        email_msg = """
         <div>
          <p>Hello：</p>
          <p>你收到这封邮件是因为在云盘选择了修改邮箱，请点击 <a href="host">确认</a>
           修改邮箱，如果您没有操作过，请忽略邮件~</p>
        </div>
        """
        send_stat = send_email_html(email_admin, '请确认修改邮箱', arg.get('email'), email_msg.replace('host', url))
        if send_stat:
            g.user.update(email_stat=1)
            return Msg.success('发送成功，请登录修改邮箱确认修改')
        return Msg.failed_dict(6000)


class Avatar(Resource):
    folder_parse = reqparse.RequestParser()
    # folder_parse.add_argument('event', required=True, type=str)
    folder_parse.add_argument('file', required=True, type=FileStorage, location='files')
    get_parse = reqparse.RequestParser()
    get_parse.add_argument('id', type=int)

    def get(self):
        arg = self.get_parse.parse_args()
        if isinstance(arg.get('id'), int):
            user_id = arg.get('id')
            user = User.get_by_id(user_id)
        else:
            user = User.verify_auth_token(request.cookies.get('assess_key'))

        if user:
            save_path = os.path.join(UPLOAD_PATH, user.use_folder)
            avatar = UserAvatar.query_one(user_id=user.id)
            if avatar:
                path = os.path.join(save_path, avatar.avatar_name)
                if os.path.exists(path):
                    with open(path, 'rb') as f:
                        data = f.read()
                else:
                    path = os.path.join(UPLOAD_PATH, 'avatar.png')
                    with open(path, 'rb') as f:
                        data = f.read()
            else:
                path = os.path.join(UPLOAD_PATH, 'avatar.png')
                with open(path, 'rb') as f:
                    data = f.read()
        else:
            path = os.path.join(UPLOAD_PATH, 'avatar.png')
            with open(path, 'rb') as f:
                data = f.read()
        resp = make_response(data)
        # resp.headers["Content-Disposition"] = "attachment; filename*=utf-8''avatar.png"
        resp.headers["Content-Type"] = f"image/png"

        return resp

    @auth_token()
    def post(self):
        arg = self.folder_parse.parse_args()
        user_id = g.user.id
        file = arg['file']
        file_data = file.read()
        file_size = len(file_data) / 1024
        config = FConfig.query_one()

        check_size = True if config.avatar_size > file_size else False
        if check_size:
            avatar = UserAvatar(user_id=user_id)
            save_path = os.path.join(UPLOAD_PATH, g.user.use_folder)
            path = os.path.join(save_path, avatar.avatar_name)
            with open(path, 'wb') as f:
                f.write(file_data)
            avatar.save()
            return Msg.success('头像保存成功')
        else:
            return Msg.failed_dict(1001)


class QueryUerName(Resource):
    parse = reqparse.RequestParser()
    parse.add_argument('username')

    @safety_strategy
    def post(self):
        arg = self.parse.parse_args()
        user = User.query_one(**arg)
        if user:
            return Msg.success(status=1)
        else:
            return Msg.success(status=0)


class CheckEmail(Resource):
    parse = reqparse.RequestParser()
    parse.add_argument('username', type=str, required=True)
    @safety_strategy
    def post(self):
        arg = self.parse.parse_args()
        user = User.query_one(**arg)
        if user:
            if user.email:
                code = LCode.create(user_id=user.id, username=user.username)

                config = FConfig.query_one()
                email_admin = config.email_info

                send_stat = send_email_html(email_admin, '授权码', user.email, code_template(code.code))
                if send_stat:
                    return Msg.success('发送成功，请登录修改邮箱确认修改')
                return Msg.failed_dict(6000)
            else:
                return Msg.failed_dict(2003)
        else:
            return Msg.failed_dict(2004)


class CheckCode(Resource):
    parse = reqparse.RequestParser()
    parse.add_argument('code', type=str, required=True)
    parse.add_argument('username', type=str, required=True)
    @safety_strategy
    def post(self):
        arg = self.parse.parse_args()
        code = LCode.query_one(**arg)
        if code:
            return Msg.success()
        else:
            return Msg.failed_dict(401)


class ResetPwd(Resource):
    parse = reqparse.RequestParser()
    parse.add_argument('code', type=str, required=True)
    parse.add_argument('username', type=str, required=True)
    parse.add_argument('password', type=str, required=True)

    @safety_strategy
    def post(self):
        arg = self.parse.parse_args()
        code = LCode.query_one(code=arg['code'], username=arg['username'])
        if code:
            code.delete()
            user = User.query_one(username=arg['username'])
            if user:
                user.set_password(arg['password'])
                user.update()
            return Msg.success()
        else:
            return Msg.failed_dict(401)


class ClearShareKey(Resource):
    @safety_strategy
    @auth_token()
    def post(self):
        user_id = g.user.id
        executor.submit(clear_share_keys, user_id)
        return Msg.success()


def clear_share_keys(id):
    from main import app
    with app.app_context():
        ShareKey.delete_by(user_id=id)
        ShareShip.delete_by(user_id=id)


api.add_resource(HelloWorld, '/hello', endpoint='hello')
api.add_resource(CtlUser, '/user', endpoint='user')
api.add_resource(QueryUerName, '/user/check', endpoint='user_check')
api.add_resource(Avatar, '/user/avatar', endpoint='avatar')
api.add_resource(Avatar, '/user/avatar.png', endpoint='avatar_png')
api.add_resource(UpdateEmail, '/user/email', endpoint='email')
api.add_resource(UpdateUser, '/user/update', endpoint='u_update')
api.add_resource(CheckEmail, '/user/checkUsername', endpoint='checkUsername')
api.add_resource(CheckCode, '/user/checkCode', endpoint='checkCode')
api.add_resource(ResetPwd, '/user/resetPwd', endpoint='resetPwd')
api.add_resource(ClearShareKey, '/user/share/clear', endpoint='share_clear')